#include "ChartView.h"
#include "log.h"
#include <qDebug>
#include <cmath>

using namespace QtCharts;

void ChartView::setUp()
{
    this->pPosTip = new QGraphicsSimpleTextItem();
    this->pPosTip->setVisible(true);
    this->pPosTip->setEnabled(false);
    this->pPosTip->setZValue(2);
    this->prePos.setX(0);
    this->prePos.setY(0);
    this->isPress = false;

    this->xLine = new QGraphicsLineItem();
    this->xLine->setPen(QPen(QColor("black")));
    this->xLine->setZValue(1);

    this->yLine = new QGraphicsLineItem();
    this->yLine->setPen(QPen(QColor("black")));
    this->yLine->setZValue(1);

    auto pChart = this->chart();
    pChart->scene()->addItem(this->xLine);
    pChart->scene()->addItem(this->yLine);
    pChart->scene()->addItem(this->pPosTip);
}

void ChartView::mouseMoveEvent(QMouseEvent* event)
{
    auto pChart = this->chart();

    if (nullptr == pChart)
    {
        QChartView::mouseMoveEvent(event);
        return;
    }

    const auto& curPos = event->pos();

    if (this->isPress)
    {
        int deltaX = this->prePos.x() - curPos.x();
        int deltaY = curPos.y() - this->prePos.y();

        pChart->scroll(deltaX, deltaY);
    }

    this->prePos = curPos;

    auto pSerise = static_cast<QLineSeries*>(pChart->series()[0]);
    const auto& pos = pChart->mapToValue(curPos, pSerise);

    auto axisX = static_cast<QValueAxis*>(pChart->axes(Qt::Horizontal)[0]);
    float x = pos.x();
    
    //放大图表后, 光标位置可能是超出轴范围的, 这种情况下不能更新数据
    if (x < axisX->min() || x > axisX->max())
    {
        QChartView::mouseMoveEvent(event);
        return;
    }

    //此处的pSerise->at(1).x()实际上就是x值与下标的倍数关系
    int index = qRound(pos.x() / pSerise->at(1).x());
    int maxIndex = pSerise->count();

    float validX = -1;
    float validY = -1;

    if (index >= 0 && index < maxIndex)
    {
        const auto& dataPoint = pSerise->at(index);

        validX = dataPoint.x();
        validY = dataPoint.y();

        this->pPosTip->setText(QString("X: %1 Y: %2").arg(validX).arg(validY));
    }

    if (validX >= 0)
    {
        const auto& dataPos = pChart->mapToPosition(QPointF(validX, validY), pSerise);
        const auto& plotArea = pChart->plotArea();
        const qreal plotAreaLeft = plotArea.x();
        const qreal plotAreaRight = plotAreaLeft + plotArea.width();
        const qreal plotAreaTop = plotArea.y();
        const qreal plotAreaBottom = plotAreaTop + plotArea.height();

        qreal lineX = dataPos.x();
        qreal lineY = dataPos.y();

        if (lineX < plotAreaRight && lineX >= plotAreaLeft)
        {
            this->xLine->setVisible(true);
            this->xLine->setLine(lineX, plotAreaTop, lineX, plotAreaBottom);
        }

        if (lineY <= plotAreaBottom && lineY > plotAreaTop)
        {
            this->yLine->setVisible(true);
            this->yLine->setLine(plotAreaLeft, lineY, plotAreaRight, lineY);
        }
        else
        {
            this->yLine->setVisible(false);
        }
    }
    else
    {
        this->hideCursor();
    }

    QChartView::mouseMoveEvent(event);
}

void ChartView::mousePressEvent(QMouseEvent* event)
{
    if (Qt::LeftButton == event->button())
    {
        this->isPress = true;
    }
    QChartView::mousePressEvent(event);
}

void ChartView::mouseReleaseEvent(QMouseEvent* event)
{
    if (Qt::LeftButton == event->button())
    {
        this->isPress = false;
    }
    QChartView::mouseReleaseEvent(event);
}

void ChartView::wheelEvent(QWheelEvent* event)
{
    auto pChart = this->chart();

    if (nullptr == pChart)
    {
        QChartView::wheelEvent(event);
        return;
    }

    this->hideCursor();

    qreal factor = std::pow(0.999, event->angleDelta().y());
    auto rect = pChart->plotArea();
    auto center = rect.center();
    rect.setWidth(rect.width() * factor);
    rect.setHeight(rect.height() * factor);
    center = 2 * center - event->position() - (center - event->position()) / factor;
    rect.moveCenter(center);
    pChart->zoomIn(rect);
    QChartView::wheelEvent(event);
}
